package com.kedacom.freedomLabel.view.activity;

import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;

import com.github.mjdev.libaums.UsbMassStorageDevice;
import com.github.mjdev.libaums.fs.FileSystem;
import com.github.mjdev.libaums.fs.UsbFile;
import com.github.mjdev.libaums.fs.UsbFileInputStream;
import com.github.mjdev.libaums.partition.Partition;
import com.google.gson.reflect.TypeToken;
import com.kedacom.freedomLabel.AppExecutors;
import com.kedacom.freedomLabel.Options;
import com.kedacom.freedomLabel.R;
import com.kedacom.freedomLabel.base.BaseActivity;
import com.kedacom.freedomLabel.databinding.ActivityExportDataBinding;
import com.kedacom.freedomLabel.model.bean.Category;
import com.kedacom.freedomLabel.model.bean.Config;
import com.kedacom.freedomLabel.model.bean.ConfigKeys;
import com.kedacom.freedomLabel.model.bean.Item;
import com.kedacom.freedomLabel.model.bean.Operator;
import com.kedacom.freedomLabel.model.bean.Product;
import com.kedacom.freedomLabel.model.bean.SharedFile;
import com.kedacom.freedomLabel.model.db.AppDatabase;
import com.kedacom.freedomLabel.model.db.DataCallback;
import com.kedacom.freedomLabel.model.db.DataLoader;
import com.kedacom.freedomLabel.model.db.dao.ConfigDao;
import com.kedacom.freedomLabel.utils.ExcelImportUtils;
import com.kedacom.freedomLabel.utils.IPUtil;
import com.kedacom.freedomLabel.utils.UsbHelper;
import com.kedacom.freedomLabel.utils.log.LLog;
import com.kedacom.freedomLabel.view.activity.server.FileDownLoadUtil;
import com.kedacom.freedomLabel.view.activity.setting.SettingActivity;
import com.kedacom.freedomLabel.viewmodel.ExportDataViewModel;
import com.kedacom.lego.annotation.ContentView;
import com.kedacom.lego.annotation.ViewModel;
import com.kedacom.lego.message.LegoMessageManager;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Locale;

import cn.bingoogolapple.qrcode.zxing.QRCodeEncoder;

@ContentView(R.layout.activity_export_data)
@ViewModel(ExportDataViewModel.class)
public class ExportDataActivity extends BaseActivity<ActivityExportDataBinding, ExportDataViewModel> {

    private ProgressDialog excelPd;
    private UsbManager mUsbManager;
    private UsbMassStorageDevice[] storageDevices;
    private static final String ACTION_USB_PERMISSION = "com.infol.density.USB_PERMISSION";
    IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    PendingIntent pendingIntent;
    private static final String BASE_DATA_FILE_NAME = "BaseConfigData.xls";
    private boolean exportData = false;

    private File exportFile;
    private SharedFile sharedFile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initUsb();

        mBinding.title.setText(String.valueOf(getIntent().getStringExtra("title")));

        sharedFile = (SharedFile) getIntent().getSerializableExtra("file");
        if (sharedFile == null || sharedFile.isError()) {
            showToast("导出文件不存在，请重试", TOAST_ERROR);
            return;
        }

        exportFile = new File(sharedFile.getPath());

        if (exportFile.exists()) {
            initView();
        } else {
            showToast("导出文件不存在，请重试", TOAST_ERROR);
        }
    }

    private void initUsb() {
        excelPd = new ProgressDialog(this);
        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        registerReceiver(usbReceiver, filter);
        pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);

    }

    // 开始导出数据
    private void initView() {
        LegoMessageManager.getInstance().sendMessage(Options.MSG_ADD_SHARED_FILE, sharedFile);
        String link = String.format(Locale.getDefault(),
                "http://%s:%d%s", IPUtil.getLocalIpStr(this),
                FileDownLoadUtil.DEFAULT_SERVER_PORT, exportFile.getAbsolutePath());
        mBinding.link.setText(link);

        mBinding.title.post(() -> {
            mBinding.QRCode.setImageBitmap(QRCodeEncoder.syncEncodeQRCode(link, 300));
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        LegoMessageManager.getInstance().sendMessage(Options.MSG_REMOVE_SHARED_FILE, sharedFile);
    }

    /**
     * 数据导入
     */
    public void importData(View view) {
        beep();
        storageDevices = UsbMassStorageDevice.getMassStorageDevices(this);

        if (storageDevices.length <= 0) {
            showToast("没有发现usb存储设备", TOAST_ERROR);
            return;
        }

        if (!checkPermission(storageDevices[0])) {  //检查是否有权限
            exportData = false;
            mUsbManager.requestPermission(storageDevices[0].getUsbDevice(), pendingIntent);
            return;
        }

        excelPd.setTitle("基础数据导入中，请稍后...");
        excelPd.setCancelable(false);
        excelPd.setCanceledOnTouchOutside(false);
        excelPd.show();

        AppExecutors.getInstance().insertIO()
                .submit(() -> {
                    try {
                        UsbFile root = readDevice(storageDevices[0]).getRootDirectory();
                        if (root == null) return;
                        UsbFile choiceFile = null;
                        for (UsbFile file : root.listFiles()) {
                            if (BASE_DATA_FILE_NAME.equals(file.getName())) {
                                choiceFile = file;
                                break;
                            }
                        }
                        if (choiceFile == null) {
                            showToast(String.format(Locale.getDefault(), "未找到文件:%s", BASE_DATA_FILE_NAME), TOAST_ERROR);
                            return;
                        }

                        List<Item> itemList = ExcelImportUtils.readSheet(new UsbFileInputStream(choiceFile), "ID",
                                new String[]{"编号", "分组", "内容", "备注"},
                                new String[]{"number", "category", "value", "remark"},
                                new Boolean[]{false, false, false, false},
                                new TypeToken<List<Item>>() {
                                }.getType());

                        List<Category> categoryList = ExcelImportUtils.readSheet(new UsbFileInputStream(choiceFile), "分组",
                                new String[]{"编号", "名称", "ID别名", "是否启用", "必填"},
                                new String[]{"number", "name", "columnNames", "status", "required"},
                                new Boolean[]{false, false, true, true, true},
                                new TypeToken<List<Category>>() {
                                }.getType());

                        List<Product> productList = ExcelImportUtils.readSheet(new UsbFileInputStream(choiceFile), "产品",
                                new String[]{"编号", "名称", "是否预设组别", "组别编号", "组别名称", "单重", "预设扣重", "上限", "下限"},
                                new String[]{"number", "name", "openGroupSetting", "groupNumber", "groupName", "singleWeight", "preTare", "topLimit", "lowLimit"},
                                new Boolean[]{false, false, false, false, false, false, false, false, false},
                                new TypeToken<List<Product>>() {
                                }.getType());

                        List<Operator> operatorList = ExcelImportUtils.readSheet(new UsbFileInputStream(choiceFile), "用户",
                                new String[]{"卡号", "用户姓名", "附加数据1", "附加数据2", "附加数据3", "备注"},
                                new String[]{"cardNumber", "name", "extraData1", "extraData2", "extraData3", "remark"},
                                new Boolean[]{false, false, false, false, false, false},
                                new TypeToken<List<Operator>>() {
                                }.getType());

                        AppDatabase.getInstance().runInTransaction(() -> {
                            try {
                                //清空item数据
                                AppDatabase.getInstance().itemDao().delete();
                                // 清除分组数据
                                AppDatabase.getInstance().categoryDao().delete();
                                // 清除产品数据
                                AppDatabase.getInstance().productDao().delete();
                                // 清除操作员数据
                                AppDatabase.getInstance().operatorDao().delete();

                                // 创建item数据
                                AppDatabase.getInstance().itemDao().save(itemList);
                                AppDatabase.getInstance().operatorDao().save(operatorList);
                                AppDatabase.getInstance().categoryDao().save(categoryList);

                                for (int i = 0; i < categoryList.size(); i++) {
                                    for (int j = 0; j < productList.size(); j++) {
                                        if (categoryList.get(i).number.equals(productList.get(j).groupNumber)) {
                                            productList.get(j).groupUUID = categoryList.get(i).uuid;
                                        }
                                    }
                                }
                                AppDatabase.getInstance().productDao().save(productList);
                                excelSuccess("导入成功");
                            } catch (Exception e) {
                                excelFail("导入失败，请检查数据的合法性。");
                                throw e;
                            }
                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                        LLog.error(e.getMessage());
                        excelFail("导出失败，请重新拔插usb设备。");
                    }

                });
    }

    /**
     * 数据导出
     */
    public void exportData(View view) {
        beep();

        ConfigDao dao = AppDatabase.getInstance().configDao();
        DataLoader.get(dao, ConfigKeys.DEVICE_CODE, new DataCallback<List<Config>>() {
            @Override
            public void success(@Nullable List<Config> data) {
                if (data == null || data.isEmpty() || TextUtils.isEmpty(data.get(0).configValue)) {
                    showToast("请在“基本信息”中设置设备编号");
                    startActivity(new Intent(ExportDataActivity.this, SettingActivity.class));
                } else {
                    startExportData(data.get(0).configValue);
                }
            }

            @Override
            public void error(@Nullable String errorMessage) {
                showToast(errorMessage);
            }
        });
    }

    private void startExportData(String configValue) {
        storageDevices = UsbMassStorageDevice.getMassStorageDevices(this);

        if (storageDevices.length <= 0) {
            showToast("没有发现usb存储设备", TOAST_ERROR);
            return;
        } else if (storageDevices.length > 1) {
            showToast("发现多个usb存储设备，请只保留一个usb存储设备", TOAST_ERROR);
            return;
        }
        if (!checkPermission(storageDevices[0])) {  //检查是否有权限
            exportData = true;
            mUsbManager.requestPermission(storageDevices[0].getUsbDevice(), pendingIntent);
            return;
        }

        excelPd.setTitle("数据导出中，请稍后...");
        excelPd.setCancelable(false);
        excelPd.setCanceledOnTouchOutside(false);
        excelPd.show();

        AppExecutors.getInstance().insertIO()
                .submit(() -> {
                    try {
                        UsbFile root = readDevice(storageDevices[0]).getRootDirectory();
                        if (root == null) {
                            excelFail("USB存储设备读取失败");
                            return;
                        }

                        // 创建对应设备的目录
                        UsbFile deviceDir = null;
                        boolean createDirSuccess = false;
                        try {
                            root.createDirectory(configValue);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        for(UsbFile usbFile:root.listFiles()){
                            if(usbFile.isDirectory() && configValue.equals(usbFile.getName())){
                                createDirSuccess = true;
                                deviceDir = usbFile;
                                break;
                            }
                        }

                        if (!createDirSuccess) {
                            excelFail("USB设备创建文件夹失败");
                            return;
                        }

                        if (UsbHelper.saveSDFileToUsb(exportFile, deviceDir, null)) {
                            excelSuccess(String.format(Locale.getDefault(), "导出成功：%s", exportFile.getName()));
                        } else {
                            excelFail("导出失败，请重试。");
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                        LLog.error(e.getMessage());
                        excelFail("导出失败，请重新拔插usb设备。");
                    }

                });
    }

    private void excelFail(String msg) {
        runOnUiThread(() -> {
            if (excelPd != null && excelPd.isShowing())
                excelPd.dismiss();
        });
        showToast(msg, TOAST_ERROR);
    }

    private void excelSuccess(String msg) {
        runOnUiThread(() -> {
            if (excelPd != null && excelPd.isShowing())
                excelPd.dismiss();
        });
        showToast(msg, TOAST_SUCCESS);
    }

    /**
     * 根据设备获取路径
     *
     * @param device
     * @return
     */
    public FileSystem readDevice(UsbMassStorageDevice device) {
        try {

            if (!checkPermission(device)) {  //检查是否有权限
                mUsbManager.requestPermission(device.getUsbDevice(), pendingIntent);
                return null;
            }

            device.init();//使用设备之前需要进行 初始化
            Partition partition = device.getPartitions().get(0); //仅使用设备的第一个分区
            FileSystem currentFs = partition.getFileSystem();
            // currentFs.getCapacity(); //容量大小
            // currentFs.getOccupiedSpace(); //已使用大小
            // currentFs.getFreeSpace();  //未使用的大小
            UsbFile root = currentFs.getRootDirectory();//获取根目录
            String deviceName = currentFs.getVolumeLabel();//获取设备标签
            return currentFs;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 检查usb设备的权限
     *
     * @param device
     * @return
     */
    public boolean checkPermission(UsbMassStorageDevice device) {
        if (mUsbManager == null) {
            return false;
        }
        if (mUsbManager.hasPermission(device.getUsbDevice())) {//有就直接读取设备是否有权限
            return true;
        } else {
            return false;
        }
    }

    public void finishActivity(View view) {
        beep();
        finish();
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(usbReceiver, filter);
    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(usbReceiver);
    }

    private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {

        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if (device != null) {
                            if (exportData) {
                                exportData(null);
                            } else {
                                importData(null);
                            }
                        }
                    } else {
                        Log.d("res", "permission denied for device " + device);
                    }
                }
            }
        }
    };

    public static void startActivity(Context context, String title, SharedFile file) {
        Intent intent = new Intent(context, ExportDataActivity.class);
        intent.putExtra("title", title);
        intent.putExtra("file", file);
        context.startActivity(intent);
    }

}
